#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <ctime>

/*****自定义结构*****/
struct Node // 单链表的结点
{
    int data;          // 存放在结点中数据的类型，在本题中为整型
    struct Node *next; // 存放后继结点的内存地址
};
typedef struct Node Node;      // 【自己的理解】重命名struct Node为Node
typedef struct Node *LinkList; // 【自己的理解】重命名struct Node *为LinkList
/*****自定义结构*****/

/*****随机生成一个长度为l的单链表（未排序并且有头结点）*****/
LinkList List_TailInsert(int l, LinkList &L)
{
    int k = 1;
    int x = 0;
    L = (LinkList)malloc(sizeof(Node)); // 创建头结点
    LinkList s;
    LinkList r = L; // r为表尾指针
    // srand(time(0));//放在这一行会导致两组随机数差不多
    while (k <= l)
    {
        x = rand() % 101;
        s = (LinkList)malloc(sizeof(Node)); // 由系统生成一个Node型的结点，同时将该结点的起始位置赋值给指针变量s
        s->data = x;
        r->next = s;
        r = s;
        k = k + 1;
        printf("%d ", x);
    }
    r->next = NULL;
    printf("\n");
    return L;
}
/*****随机生成一个长度为l的单链表（未排序并且有头结点）*****/

/*****对单链表进行冒泡排序（结合了输出功能）*****/
LinkList BubbleSort(LinkList &L)
{
    LinkList pa, pb, pc;
    int c = 0;
    pa = L->next;
    pb = L->next->next;
    pc = L->next;
    int j = 1;

    /***求链表长度***/
    int l = 0;
    while (pc != NULL)
    {
        l = l + 1;
        pc = pc->next;
    }
    /***求链表长度***/

    while (j < l)
    {
        if (pa->data > pb->data)
        {
            c = pb->data;
            pb->data = (int)pa->data;
            pa->data = c;
            j = 1;
        }
        else
        {
            j = j + 1;
        }
        pb = pb->next;
        pa = pa->next;
        if (pa->next == NULL && j != l)
        {
            j = 1;
            pa = L->next;
            pb = L->next->next;
        }
    }
    pc = L->next;
    while (pc != NULL)
    {
        printf("%d ", pc->data);
        pc = pc->next;
    }
    printf("\n");
    return L;
}
/*****对单链表进行冒泡排序（结合了输出功能）*****/

/*****核心功能函数1：排序后单链表删重函数optimize*****/
LinkList opt(LinkList &L)
{
    LinkList p0, p1;
    p0 = L->next;
    p1 = p0->next;
    while (p1 != NULL)
    {
        if (p0->data != p1->data)
        {
            p0 = p0->next;
            p1 = p1->next;
        }
        else
        {
            p1 = p1->next;
            p0->next = p1;
        }
    }
    return L;
}
/*****核心功能函数1：排序后单链表删重函数optimize*****/

/*****核心功能函数2：归并链表*****/
LinkList MergeList(LinkList &La, LinkList &Lb) // 【自己的理解】LinkList &La就是La头结点的内存地址，也就是头指针
                                               // 通常用头指针来标识一个单链表
{
    LinkList pa, pb, pc, q; // LinkList是自定义的指针类型
    pa = La->next;          // 把单链表A头结点的指针【域】赋给pa
    pb = Lb->next;          // 把单链表B头结点的指针【域】赋给pb
    pc = La;                // 初始化pc，防止pc变成野指针，同时将pc作为链表合并后新的头节点
                            // 此时新头节点pc在La，pc作为pa的前驱节点链接pa
                            // pc作为pa的前驱节点，意义在于游标

    while (pa != NULL && pb != NULL) // La和Lb任意一条链表为空时跳出while循环
    {
        if (pa->data < pb->data) // 如果pa的值小于pb，则pb不插入，pb不动，pa前进
        {
            pc->next = pa;
            pc = pa;
            pa = pa->next; // 插入pa以后，pa前进，剩下的结点和La看作整体进行比较
        }
        else if (pa->data > pb->data) // 若pa的值大于pb，则需要把pb插在pa的前边
        {
            pc->next = pb;
            pc = pb;
            pb = pb->next; // 插入pb以后，pb前进，剩下的结点和Lb看作整体进行比较
        }
        else // 如果pa的值小于pb，则pb不插入，pb前进，pa前进
        {
            pc->next = pa;
            pc = pa;
            pa = pa->next;
            q = pb;
            pb = pb->next;
            free(q);
        }
    }

    pc->next = pa ? pa : pb; // 插入剩余结点，由于之前删重了，所以不会有重复的元素

    free(Lb);
    return La;
}
/*****核心功能函数2：归并链表*****/

/*****主函数*****/
int main()
{
    /*生成两个乱序的单链表，这里规定了第一个长度为12，第二个长度为8*/
    LinkList La = NULL;
    LinkList Lb = NULL;
    srand(time(0));
    printf("  生成的第一个单链表：");
    List_TailInsert(12, La);
    printf("  生成的第二个单链表：");
    List_TailInsert(8, Lb);

    /*对两个链表进行排序（结合了输出功能）*/
    printf("排序后的第一个单链表：");
    La = BubbleSort(La);
    printf("排序后的第二个单链表：");
    Lb = BubbleSort(Lb);

    /*对排序后的单链表进行优化（删除单链表中的重复数据）*/
    La = opt(La);
    Lb = opt(Lb);

    /*执行功能函数*/
    La = MergeList(La, Lb);

    /*输出符合题意的单链表*/
    printf("按题意处理后的单链表：");
    LinkList pp = La->next;
    while (pp != NULL)
    {
        printf("%d ", pp->data);
        pp = pp->next;
    }
    printf("\n");

    system("pause"); // 防止运行后自动退出，需头文件【stdlib.h】
}
/*****主函数*****/